package com.zwk.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zwk.common.utils.PageUtils;
import com.zwk.common.utils.Query;
import com.zwk.common.constant.ProductConstant;
import com.zwk.gulimall.product.dao.AttrDao;
import com.zwk.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.zwk.gulimall.product.entity.AttrEntity;
import com.zwk.gulimall.product.entity.CategoryEntity;
import com.zwk.gulimall.product.event.AttrEvent;
import com.zwk.common.constant.EventType;
import com.zwk.gulimall.product.service.AttrAttrgroupRelationService;
import com.zwk.gulimall.product.service.AttrGroupService;
import com.zwk.gulimall.product.service.AttrService;
import com.zwk.gulimall.product.service.CategoryService;
import com.zwk.gulimall.product.vo.AttrResVo;
import com.zwk.gulimall.product.vo.AttrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService , ApplicationContextAware {

    private ApplicationContext context;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private AttrGroupService groupService;

    @Autowired
    private AttrAttrgroupRelationService relationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public boolean save(AttrVo attrVo) {
        AttrEntity attr = new AttrEntity();
        BeanUtils.copyProperties(attrVo,attr);
        boolean save = this.save(attr);
        if (attr.getAttrType().equals(ProductConstant.AttrEnum.ATTR_TYPE_ALL.getCode())||attr.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //id是插入时自动生成的，所以这里需要重新获取
            attrVo.setAttrId(attr.getAttrId());
            context.publishEvent(new AttrEvent(attrVo, EventType.SAVE));
        }
        return save;
    }

    public PageUtils queryAttrPage(Map<String, Object> params, Long catelogId,ProductConstant.AttrEnum attrType){
        IPage<AttrEntity> page = new Query<AttrEntity>().getPage(params);
        LambdaQueryWrapper<AttrEntity> wrapper=new LambdaQueryWrapper<>();
        wrapper.and(w->{
            w.eq(AttrEntity::getAttrType,ProductConstant.AttrEnum.ATTR_TYPE_ALL.getCode()).or();
            switch (attrType){
                case ATTR_TYPE_BASE: w.eq(AttrEntity::getAttrType,ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()); break;
                case ATTR_TYPE_SALE: w.eq(AttrEntity::getAttrType,ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode()); break;
            }
        });
        if (catelogId!=0){
            wrapper.eq(AttrEntity::getCatelogId,catelogId);
        }
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)){
            wrapper.and((w)->{
                w.eq(AttrEntity::getAttrId,key).or().like(AttrEntity::getAttrName,key);
            });
        }
        //构造完条件
        IPage<AttrEntity> resultPage = this.page(page, wrapper);
        List<AttrResVo> result = resultPage.getRecords().stream().map(attr -> {
            AttrResVo vo = new AttrResVo();
            BeanUtils.copyProperties(attr, vo);

            AttrAttrgroupRelationEntity relation = relationService.getOne(
                    new LambdaQueryWrapper<AttrAttrgroupRelationEntity>().eq(AttrAttrgroupRelationEntity::getAttrId, attr.getAttrId())
            );
            if (relation!=null){
                Long groupId = relation.getAttrGroupId();
                String groupName = groupService.getById(groupId).getAttrGroupName();
                vo.setGroupName(groupName);
            }
            CategoryEntity categoryEntity = categoryService.getById(attr.getCatelogId());
            if (categoryEntity!=null) {
                String categoryName = categoryEntity.getName();
                vo.setCatelogName(categoryName);
            }
            return vo;
        }).collect(Collectors.toList());
        return new PageUtils(resultPage,result);
    }

    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
        return this.queryAttrPage(params,catelogId,ProductConstant.AttrEnum.ATTR_TYPE_BASE);
    }

    @Override
    public PageUtils querySaleAttrPage(Map<String, Object> params, Long catelogId) {
        return this.queryAttrPage(params,catelogId,ProductConstant.AttrEnum.ATTR_TYPE_SALE);
    }

    @Override
    public AttrResVo getAttrInfo(Long attrId) {
        AttrResVo resVo=new AttrResVo();
        AttrEntity attrEntity = this.getById(attrId);
        if (attrEntity==null){
            return null;
        }
        BeanUtils.copyProperties(attrEntity,resVo);
        AttrAttrgroupRelationEntity relation = relationService.getOne(
                new LambdaUpdateWrapper<AttrAttrgroupRelationEntity>().eq(AttrAttrgroupRelationEntity::getAttrId, attrId)
        );
        if (relation!=null){
            resVo.setAttrGroupId(relation.getAttrGroupId());
        }
        List<CategoryEntity> catelogPath = categoryService.findCatelogPath(resVo.getCatelogId());
        List<Long> collect = catelogPath.stream().map(category ->category.getCatId()).collect(Collectors.toList());
         resVo.setCatelogPath(collect.toArray(new Long[]{}));
        return resVo;
    }


    @Override
    @Transactional
    public void updateAttr(AttrVo attrVo) {
        this.updateById(attrVo);
        if (attrVo.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_ALL.getCode()||attrVo.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            context.publishEvent(new AttrEvent(attrVo, EventType.UPDATE));
        }
    }

    @Override
    public List<Long> selectSearchAttrs(List<Long> attrIds) {

        List<Long> searchAttrIds = this.baseMapper.selectSearchAttrIds(attrIds);

        return searchAttrIds;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context=applicationContext;
    }
}